﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using SimpleTaskManager.Domain.Abstract;
using SimpleTaskManager.Domain.Entities;

namespace SimpleTaskManager.Domain.Concrete
{
    /// <summary>
    /// A repository containing the users of the application and interaction logic on them
    /// </summary>
    public class EFUserRepository : IUserRepository
    {
        private EFDbContext context = new EFDbContext();

        /// <summary>
        /// Gets the collection of the users
        /// </summary>
        public IQueryable<User> Users
        {
            get { return context.Users; }
        }

        /// <summary>
        /// Removes a user from the collection
        /// </summary>
        /// <param name="id">The ID of the user who will be removed</param>
        public void DeleteUser(int id)
        {
            User user = context.Users.Single(u => u.UserID == id);
            foreach(var task in user.LeaderOf.Where(t => t.Status != TaskStatusEnum.Finished))
            {
                task.RemoveLeader();
            }
            foreach (var task in user.Tasks)
            {
                task.Group.Remove(user);
            }
            user.Status = StatusEnum.InActive;
            context.Entry(user).State = EntityState.Modified;
            context.SaveChanges();
        }

        /// <summary>
        /// Saves the modifications of a user
        /// </summary>
        /// <param name="user">The user to modify</param>
        public void EditUser(User user)
        {
            context.Entry(user).State = EntityState.Modified;
            context.SaveChanges();
        }

        /// <summary>
        /// Adds a new user to the collection
        /// </summary>
        /// <param name="user">The new user to add</param>
        /// <param name="encrypter">The encrypter which can be used to hash the user's password.</param>
        public void CreateUser(User user, IPasswordEncrypter encrypter)
        {
            user.CreationDate = DateTime.Now;
            user.Tasks = new List<Task>();
            user.Tasks.Add(context.Tasks.Single(t => t.Name == "Internal Project"));

            //hash the password
            user.Password = encrypter.HashPassword(user.Password);

            context.Users.Add(user);
            context.SaveChanges();
        }

        /// <summary>
        /// Encrypts the given password and sets it as the password for the given user.
        /// </summary>
        /// <param name="user">The user whos password will be replaced.</param>
        /// <param name="password">The password which will be encrypted and set to the user.</param>
        /// <param name="encrypter">The encrypter which can be used to hash the user's password.</param>
        public void ChangeUserPassword(User user, string password, IPasswordEncrypter encrypter)
        {
            user.Password = encrypter.HashPassword(password);
            context.Entry(user).State = EntityState.Modified;
            context.SaveChanges();
        }


        /// <summary>
        /// Adds new User_Skill (association between skill and user)
        /// </summary>
        /// <param name="p">userID</param>
        /// <param name="skill">skill to be added for the user specified by parameter p</param>
        public void AddSkill(int p, User_Skill skill)
        {
            var user = context.Users.Single(u => u.UserID == p);
            if(!user.User_Skills.Any(s => s.SkillId == skill.SkillId))
                user.User_Skills.Add(skill);
            context.SaveChanges();
        }
    }
}
